'''
Created on 29/03/2011

@author: Eran_Z

Weighting
'''

import search_m
from util_m import sum
from math import log

#Helper functions

def __singleNGDWeight(term1, term2):
    return 0 if term1 == term2 else max(0, 1 - search_m.NGD(term1, term2))

def __singleMutualInformationWeight(term1, term2):
    return 0 if term1 == term2 else search_m.searchTogether(term1, term2)*1.0/(search_m.searchSingle(term1)*search_m.searchSingle(term2))

def __pij(ci, wj, hi):
    return search_m.searchTogether(ci, wj)*1.0/hi

def __plogp(ci, wj, hi):
    p = __pij(ci, wj, hi)
    return p * log(p, 2)


#Main functions
def uniformWeighter(context, world):
    return [1]*len(context)

def NGDWeighter(context, world):
    #TODO: test
    return map(lambda ci: reduce(sum, map(lambda cj: __singleNGDWeight(ci, cj), context)), context)

def mutualInformationWeighter(context, world):
    #TODO: test
    return map(lambda ci: reduce(sum, map(lambda cj: __singleMutualInformationWeight(ci, cj), context)), context)

def entropyWeighter(context, world):
    #h[i] = sigma(j=1..n) #(ci, wj)
    h = map(lambda c: reduce(sum, map(lambda w: search_m.searchTogether(c, w), world)), context)
    H = map(lambda i: -reduce(sum, map(lambda w: __plogp(context[i], w, h[i]), world)), range(len(context)))
    sigma_H = reduce(sum, H)
    return map(lambda i: 1-(H[i]*1.0/sigma_H), range(len(context)))

def regularSupervisedWeighter(context, world):
    #TODO: stub
    pass

def normalizedSupervisedWeighter(context, world):
    #TODO: stub
    pass

weightingAlgorithms = {"Uniform": uniformWeighter, "NGD": NGDWeighter, "Mutual Information": mutualInformationWeighter,
                       "Entropy": entropyWeighter, "Regular Supervised": regularSupervisedWeighter,
                       "Normalized Supervised": normalizedSupervisedWeighter }
